#include<iostream>

using namespace std ;

const int maxn = 100010 ;

//因为要维护每个集合中点的数量，所以加一个size[],表示每个点所在的集合中点的数量，而且规定只有父节点的size才有意义
int n , m ;
int p[maxn] , size1[maxn];

//查找祖先结点
int find(int x) {
    if(find(x) != x) {
        p[x] = find(p[x]);
    }
    return p[x];
}

int main() {

    cin >> n >> m ;

    for (int i = 0; i < n; ++i) {
        p[i] = i ;
        size1[i] = 1 ;   //每个集合初始的时候size = 1
    }

    while(m--){
        char op[5] ;
        scanf("%s" , op);
        if(op[0] == 'C'){   //两个集合合并
            int a , b ;
            cin >> a >> b;
            if(find(a) == find(b)) {
                continue ;
            }
            p[find(a)] = find(b) ;
            //祖先结点是记录两个集合数量的，合并时把他们的size相加一下
            size1[find(b)] += size1[find(a)] ;
        } else if(op[1] == '1') {
            //判断a 和b 是否在一个连通块中
            int a , b ;
            cin >> a >> b;
            if(find(a) == find(b)) {
                puts("Yes");
            }
        } else if (op[1] == '2') {
            //询问a中的点的数量
            int a ;
            cin >> a;
            printf("%d\n" , size1[a]);
        }

    }

    return 0 ;
}